<?php
declare(strict_types=1);

namespace Service\PayService\Payer;

use Service\BaseService;
use Service\Code\Normal;
use Service\MessageService\PayNotifyService;
use Service\ChannelService\ChannelWxService;
use Service\VenderClient\PayCenterApi\AllinpayApiClient;
use Service\ConfigureService\ChannelConfigService;
use Service\ChannelService\StoreConfigService;
use Service\UserService\MnUserService;
use Service\PayService\CashPayService;
use App\Model\BbcModel\Mnuser;
use Service\AreaService\AreaService;

/**
 * 通联支付
 * @author chenshubo
 */
class Allinpay extends BaseService
{    
    public $checktime = 200;
    
    
    /**
     * 扫码支付
     * @param int $cid
     * @param int $mn_sid
     * @param array $extra
     */
    public function scanPay(int $cid,int $mn_sid,int $mnid,array $param)
    {
        $store_type = $param['store_type'];
//        if( $store_type == MnUserService::TYPE_O2O ) {
//            $config = ChannelConfigService::instance()->getChannelConfig('allinpay_pay', $cid);
//        }
//        elseif( $store_type == MnUserService::TYPE_QZ ) {
//            $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
//        }
        $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
        if(empty($config)) {
            return Normal::returnCode(Normal::FAIL,"通联支付未配置");
        }
        $terminalInfoSN=$param['cash_register']['sn']??'';
        if(!$terminalInfoSN){
            return Normal::returnCode(Normal::FAIL,"通联支付收银台终端信息未配置");
        }
        $config['cid']  = $cid;
        $config['mnid'] = 4;
        if( !empty($param['auth_code']) ) {
            if( substr($param['auth_code'], 0,2) >= 20 ) {
                $authcodetype   = 'ALIPAY';
                $auth_user_pay_type= CashPayService::AUTH_USER_PAY_ALIPAY;
            }else{
                $authcodetype   = 'WECHATPAY';
                $auth_user_pay_type= CashPayService::AUTH_USER_PAY_WEIXIN;
            }
        }
        $ip=getIp()??'127.0.0.1';
        $order = [
            'reqsn'         => $param['out_trade_no'], //商户交易订单号
            'body'          => $param['body'],//商户显示名称
            'total_fee'     => $param['total_fee'],//订单金额
            'authcode'      => $param['auth_code'],//付款方账户
            'termno'        => $terminalInfoSN,
            'deviceip'      => $ip
        ];
        
        //前置仓
        $payreport_data = [];
        if( $store_type == MnUserService::TYPE_QZ && $param['is_order'] == 1 ) {
            $companyConfig = StoreConfigService::instance()->getConfig('e_company', $mn_sid);
            if(empty($companyConfig)) {
                return Normal::returnCode(Normal::FAIL,"电商平台未配置");
            }
            $payreport_data= [
                'cid'           => $cid,
                'company'       => $companyConfig,
                'payconfig'     => $config,
                'pay_type'      => 'allinpay',
                'pay_serial'    => '',
                'pay_sn'        => $param['out_trade_no']
            ];
        }
        
        //调用支付接口
        $initalRequest = json_encode($order,JSON_UNESCAPED_UNICODE);
        $client = (new AllinpayApiClient($config));
        $result_call = $client->scanPayOrder($order);
        if( $result_call['code'] != Normal::SUC ) {
            return $result_call;
        }
        
        $response = $result_call['data'];
        if( $response['trxstatus'] =='0000' ) 
        {
            if( $store_type == MnUserService::TYPE_QZ && $param['is_order'] == 1 ) {
                $payreport_data['pay_serial'] = $response['trxid'];
                //PayDeclareService::instance()->publishMsg($payreport_data);
                //$result_call['data']['payreport_data']=$payreport_data;
            }
            return Normal::returnCode(Normal::SUC,"处理成功",[
                'transaction_id'    => $response['trxid'],
                'initalRequest'     => $initalRequest,
                'initalResponse'    => json_encode($response,JSON_UNESCAPED_UNICODE),
                'auth_user_pay_type'=> $auth_user_pay_type,
                'payreport_data'    => $payreport_data,
                'pay_time'          => $response['fintime']?strtotime($response['fintime']):0
            ]);
        }
        else
        {
            $order['time']          = 0 ;
            $order['cid']           = $cid;
            $order['mn_sid']        = $mn_sid;
            $order['store_type']    = $param['store_type'];
            $order['initalRequest'] = $initalRequest;
            $order['auth_user_pay_type']=$auth_user_pay_type;
            $order['payreport_data']=$payreport_data;
            $order['is_order']      =$param['is_order'];
            return $this->checkScanOrderPay($order,$config);
        }
    }
    /**
     * 创建支付订单
     * @param int $cid
     * @param int $mn_sid
     * @param array $extra
     */
    public function userPay(int $cid,int $mn_sid,int $mnid,array $extra = [])
    {
        //渠道配置
        $config = ChannelConfigService::instance()->getChannelConfig('allinpay_pay', $cid);
        if(empty($config)) {
            return Normal::returnCode(Normal::FAIL,"通联支付未配置");
        }
        
        //获取回调
        $callback_url = PayNotifyService::instance()->getChannelNotifyHost($cid);
        if( empty($callback_url) ) {
            return Normal::returnCode(Normal::FAIL,"通联支付回调地址未配置");
        }
        
        $wx_config = ChannelWxService::instance()->queryWxConfig($cid);
        if( empty($wx_config) ) {
            return Normal::returnCode(Normal::FAIL,"通联支付微信appid未配置");
        }
        
        if( $mn_sid == TO_C_MNID_TYPE ) {
            $appid = $wx_config['s_app_id'];
        } else {
            $appid = $wx_config['app_id'];
        }
        $order_no = $extra['order_no'];
        $noticeUrl = "http://{$callback_url}/webapi/pay/notify/{$cid}/{$mn_sid}/{$mnid}/allinpay/{$order_no}";
        $order = [
            'reqsn'         => $order_no, //商户交易订单号
            'body'          => "在线下单",//商品名称
            'trxamt'        => bcmul((string)$extra['money'],'100'),
            'paytype'       => 'W06',//小程序支付类型
            'remark'        => '1',
            'validtime'     => 20,
            'acct'          => $extra['open_id'],//付款方账户
            'notify_url'    => $noticeUrl,
            'sub_appid'     => $appid,
        ];
        $client = (new AllinpayApiClient($config));
        $result = $client->payOrder($order);
        if( $result['code'] != Normal::SUC ) {
            return $result;
        }
        return Normal::returnCode(Normal::SUC,"处理成功",[
            'payInfo'       => $result['data'],
            'payRequest'    => json_encode($order,JSON_UNESCAPED_UNICODE),
            'payResponse'   => json_encode($result['data'],JSON_UNESCAPED_UNICODE),
        ]);
    }
    
    /**
     *  解析body内容
     * @param $body
     */
    public function getNotify($body)
    {
        //解析回调body内容
    }
    
    /**
     * 查询支付
     * @param array $param
     */
    public function checkScanOrderPay( array $param = [],array $payconfig=[] )
    {
        sleep(5);
        $param['time'] += 5;
        
        $body=[
            'reqsn'=>$param['reqsn']
        ];
        
        //调用查询支付订单状态接口
        $client = (new AllinpayApiClient($payconfig));
        $result_query = $client->queryPay($body);
        if( $result_query['code'] != Normal::SUC ) {
            return $result_query;
        }
        $payreport_data=$param['payreport_data'];
        $response = $result_query['data'];
        if( isset($response['trxstatus']) && $response['trxstatus'] == '0000' ) {
            if( $param['store_type'] == MnUserService::TYPE_QZ && $param['is_order'] == 1 ) {
                
                $payreport_data['pay_serial'] = $response['trxid'];
                //PayDeclareService::instance()->publishMsg($payreport_data);
            }
            return Normal::returnCode(Normal::SUC,"处理成功",[
                'transaction_id'    => $response['trxid'],
                'initalRequest'     => $param['initalRequest'],
                'initalResponse'    => json_encode($response,JSON_UNESCAPED_UNICODE),
                'auth_user_pay_type'=>$param['auth_user_pay_type'],
                'payreport_data'    =>$payreport_data,
                'pay_time'          => $response['fintime']?strtotime($response['fintime']):0
            ]);
        }
        
        if ( $param['time'] >= $this->checktime ) {
            return Normal::returnCode(Normal::FAIL,"通联支付交易超时,请重试,已重试40次!");
        }
        
        return $this->checkScanOrderPay($param,$payconfig);
    }
    
    public function scanPayRefund(int $cid,int $mn_sid,int $mnid,array $param){
        $store_type = $param['store_type'];
//        if( $store_type == MnUserService::TYPE_O2O ) {
//            $config = ChannelConfigService::instance()->getChannelConfig('allinpay_pay', $cid);
//        }
//        elseif( $store_type == MnUserService::TYPE_QZ ) {
//            $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
//        }
        $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
        if(empty($config)) {
            return Normal::returnCode(Normal::FAIL,"支付未配置");
        }
        
        $order_data = [
            'reqsn' => (string)$param['out_refund_no'],
            'oldreqsn' =>(string)$param['out_trade_no'],
            'total_fee' => $param['total_fee'],
            'refund_fee' => $param['refund_fee'],
        ];
        $client = (new AllinpayApiClient($config));
        $result_call = $client->orderRefund($order_data);
        if( $result_call['code'] != Normal::SUC ) {
            return $result_call;
        }
        $response = $result_call['data'];
        if( $response['trxstatus'] =='0000' ) {
                return Normal::returnCode(Normal::SUC,'退款成功',$response);
        }else{
            $order_data['time']=0;
            return $this->checkReturnPay($order_data,$config);
        }
    }
    
    /**
     * 查询退款
     * @param array $param
     * @param array $payconfig
     * @return type
     */
    public function checkReturnPay(array $param = [],array $payconfig=[]) {
        sleep(5);
        $param['time'] += 5;
        $order=[
            'reqsn'=>$param['reqsn']
        ];
        
        //调用查询支付订单状态接口
        $client = (new AllinpayApiClient($payconfig));
        $result_query = $client->queryPay($order);
        if( $result_query['code'] != Normal::SUC ) {
            return $result_query;
        }
        $response = $result_query['data'];
        if(isset($response['trxstatus']) && $response['trxstatus'] == '0000'){
            return Normal::returnCode(Normal::SUC,'退款成功',$response);
        }
        if ( $param['time'] >= $this->checktime ) {
            return Normal::returnCode(Normal::FAIL,"通联支付交易超时,请重试,已重试40次!");
        }
        
        return $this->checkReturnPay($param,$payconfig);
        
    }
    
    public function addTerm(int $mn_sid,array $param) {
        if(empty($mn_sid)){
            return Normal::returnCode(Normal::FAIL,"店铺id必传");
        }
        if(empty($param['termno'])){
            return Normal::returnCode(Normal::FAIL,"终端编号必传");
        }
        $mn_user= Mnuser::instance()->info(['id'=>$mn_sid]);
        if(empty($mn_user)){
            return Normal::returnCode(Normal::FAIL,"未找到店铺");
        }
        $cid=$mn_user['pid'];
        $store_type = $mn_user['type'];
//        if( $store_type == MnUserService::TYPE_O2O ) {
//            $config = ChannelConfigService::instance()->getChannelConfig('allinpay_pay', $cid);
//        }
//        elseif( $store_type == MnUserService::TYPE_QZ ) {
//            $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
//        }
        $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
        if(empty($config)) {
            return Normal::returnCode(Normal::FAIL,"通联支付未配置");
        }
        if( $mn_user['province'] == 0 ) {
            return Normal::returnCode(Normal::FAIL, '请配置门店自提收货地址[省份]');
        }
        
        if( $mn_user['city'] == 0 ) {
            return Normal::returnCode(Normal::FAIL, '请配置门店自提收货地址[市]');
        }
        
        if( $mn_user['area'] == 0 ) {
            return Normal::returnCode(Normal::FAIL, '请配置门店自提收货地址[区/县]');
        }
        
        if( empty($mn_user['address']) ) {
            return Normal::returnCode(Normal::FAIL, '请配置门店自提收货地址[详细地址]');
        }
        $areas = AreaService::instance()->queryAreaListById([
            $mn_user['province'],
            $mn_user['city'],
            $mn_user['area']
        ]);
        $address=$areas[$mn_user['province']]['name'].'-'.$areas[$mn_user['city']]['name'].'-'.$areas[$mn_user['area']]['name'].'-'.$mn_user['address'];
        $order = [
            'termno'         => $param['termno'], //终端号
            'termaddress'   => $address,//
        ];
        if(isset($param['operation'])&&$param['operation']=='01'){
            $order['operation']=$param['operation'];
        }
        $client = (new AllinpayApiClient($config));
        return $client->addTerm($order);
    }
    
    public function queryTerm(int $mn_sid,array $param) {
        if(empty($mn_sid)){
            return Normal::returnCode(Normal::FAIL,"店铺id必传");
        }
        if(empty($param['termno'])){
            return Normal::returnCode(Normal::FAIL,"终端编号必传");
        }
        $mn_user= Mnuser::instance()->info(['id'=>$mn_sid]);
        if(empty($mn_user)){
            return Normal::returnCode(Normal::FAIL,"未找到店铺");
        }
        $cid=$mn_user['pid'];
        $store_type = $mn_user['type'];
//        if( $store_type == MnUserService::TYPE_O2O ) {
//            $config = ChannelConfigService::instance()->getChannelConfig('allinpay_pay', $cid);
//        }
//        elseif( $store_type == MnUserService::TYPE_QZ ) {
//            $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
//        }
        $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
        if(empty($config)) {
            return Normal::returnCode(Normal::FAIL,"通联支付未配置");
        }
        $order = [
            'termno'         => $param['termno'], //终端号
        ];
        $client = (new AllinpayApiClient($config));
        return $client->queryTerm($order);
    }
    
    public function delTerm(int $mn_sid,array $param) {
        if(empty($mn_sid)){
            return Normal::returnCode(Normal::FAIL,"店铺id必传");
        }
        if(empty($param['termno'])){
            return Normal::returnCode(Normal::FAIL,"终端编号必传");
        }
        $mn_user= Mnuser::instance()->info(['id'=>$mn_sid]);
        if(empty($mn_user)){
            return Normal::returnCode(Normal::FAIL,"未找到店铺");
        }
        $cid=$mn_user['pid'];
        $store_type = $mn_user['type'];
//        if( $store_type == MnUserService::TYPE_O2O ) {
//            $config = ChannelConfigService::instance()->getChannelConfig('allinpay_pay', $cid);
//        }
//        elseif( $store_type == MnUserService::TYPE_QZ ) {
//            $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
//        }
        $config = StoreConfigService::instance()->getConfig('allinpay_pay', $mn_sid);
        if(empty($config)) {
            return Normal::returnCode(Normal::FAIL,"通联支付未配置");
        }
        $order = [
            'termno'         => $param['termno'], //终端号
        ];
        $client = (new AllinpayApiClient($config));
        return $client->delTerm($order);
    }
}
